import java.util.{Scanner, StringTokenizer}

import scala.collection.mutable.ArrayBuffer
import scala.io.Source

object Sheet4 {
  def main(args: Array[String]): Unit = {
    val gizmos = Map("Apple" -> 10, "Pear" -> 20, "Banana" -> 30)
    val discounted = gizmosDiscount(gizmos)

    val result1 = discounted.mkString(", ")
    println(result1)

    val result2 = countWordsFun("src/myFile.txt")
    println(result2)

    val result3 = countWords1("src/myFile.txt")
    println(result3)

    val result4 = countWords2("src/myFile.txt")
    println(result4)

    val result5 = countWords3("src/myFile.txt")
    println(result5)

    val result6 = countWords4("src/myFile.txt")
    printer(result6)

    val result7 = mapWeekDay("Sunday")
    println(result7)

    printSystemProperties()

    val result8 = minmax(Array(1, 2, 3, 4, 5, 6, 7))
    println(result8)

    val result9 = lteqgt(Array(1, 2, 3, 4, 5, 6, 7), 4)
    println(result9)

    val result10 = question6()
    println(result10)

    val result11 = question9(Array(1, 2, 3, 4, 5, 6, 7), 4)
    println(result11)
  }

  def gizmosDiscount(gizmos: Map[String, Int]): Map[String, Double] = {
    gizmos.map(x => (x._1, x._2 * 0.9))
  }

  def countWordsFun(path: String): Map[String, Int] = {
    val source = Source.fromFile(path)
    try {
      val arrayBuffer = ArrayBuffer[(String, Int)]()
      source.getLines().foreach(line => arrayBuffer ++= line.split(" ").map((_, 1)))
      arrayBuffer.groupBy(_._1).mapValues(x => (0 /: x) ((x, y) => x + y._2))
    } finally {
      source.close()
    }
  }

  def countWords1(path: String): Map[String, Int] = {
    val source = Source.fromFile(path)
    try {
      val words = ArrayBuffer[String]()
      val counter = scala.collection.mutable.Map[String, Int]()
      source.getLines().foreach(line => words ++= line.split(" "))
      for (word <- words) {
        counter(word) = counter.getOrElse(word, 0) + 1
      }
      counter.toMap
    } finally {
      source.close()
    }
  }

  def countWords2(path: String): Map[String, Int] = {
    val source = Source.fromFile(path)
    try {
      val words = ArrayBuffer[String]()
      var counter = Map[String, Int]()
      source.getLines().foreach(line => words ++= line.split(" "))
      for (word <- words) {
        val count = counter.getOrElse(word, 0) + 1
        counter += (word -> count)
      }
      counter
    } finally {
      source.close()
    }
  }

  def countWords3(path: String): collection.mutable.SortedMap[String, Int] = {
    val source = Source.fromFile(path)
    try {
      val words = ArrayBuffer[String]()
      val counter = scala.collection.mutable.SortedMap[String, Int]()
      source.getLines().foreach(line => words ++= line.split(" "))
      for (word <- words) {
        counter(word) = counter.getOrElse(word, 0) + 1
      }
      counter
    } finally {
      source.close()
    }
  }

  def countWords4(path: String): Map[String, Int] = {
    val source = Source.fromFile(path)
    try {
      val words = ArrayBuffer[String]()
      import scala.collection.JavaConverters.mapAsScalaMap
      val counter: scala.collection.mutable.Map[String, Int] = mapAsScalaMap(new java.util.TreeMap[String, Int])
      source.getLines().foreach(line => words ++= line.split(" "))
      for (word <- words) {
        counter(word) = counter.getOrElse(word, 0) + 1
      }
      counter.toMap
    } finally {
      source.close()
    }
  }

  def mapWeekDay(weekDay: String): String = {
    val mapper = scala.collection.mutable.LinkedHashMap[String, (Int, String)]()
    mapper += (
      "Monday" -> (java.util.Calendar.MONDAY, "java.util.Calendar.MONDAY"),
      "Tuesday" -> (java.util.Calendar.TUESDAY, "java.util.Calendar.TUESDAY"),
      "Wednesday" -> (java.util.Calendar.WEDNESDAY, "java.util.Calendar.WEDNESDAY"),
      "Thursday" -> (java.util.Calendar.THURSDAY, "java.util.Calendar.THURSDAY"),
      "Friday" -> (java.util.Calendar.FRIDAY, "java.util.Calendar.FRIDAY"),
      "Saturday" -> (java.util.Calendar.SATURDAY, "java.util.Calendar.SATURDAY"),
      "Sunday" -> (java.util.Calendar.SUNDAY, "java.util.Calendar.SUNDAY")
    )
    //    println(setter.getOrElse(weekDay, (0, "Not Found"))._2)
    val maybe = mapper.get(weekDay)
    maybe match {
      case Some(b: (Int, String)) => b._2
      case _ => "Not Found!"
    }
  }

  def printSystemProperties(): Unit = {
    import scala.collection.JavaConverters.propertiesAsScalaMapConverter
    val table = java.lang.System.getProperties.asScala

    val longestKey = table.keySet.maxBy(x => x.length)
    println(s"longestKey entry is => $longestKey -> ${table(longestKey)}")
    println("Java System Properties Below: ")
    table.filter(_._1.startsWith("java")).foreach(x => printf("%s\t\t\t\t\t| %s %n", x._1, x._2))
  }

  def minmax(values: Array[Int]): (Int, Int) = {
    (values.min, values.max)
  }

  def lteqgt(values: Array[Int], v: Int): (Int, Int, Int) = {
    val statistics = values.groupBy(x => if (x > v) 1 else if (x < v) -1 else 0)
    (
      statistics.getOrElse(-1, Array.empty).length,
      statistics.getOrElse(0, Array.empty).length,
      statistics.getOrElse(1, Array.empty).length,
    )
  }

  def question6(): Map[String, Int] = {
    var map = Map[String, Int]()
    val list = classOf[java.util.Calendar].getFields
    list.foreach(x => {
      if (x.getName.endsWith("DAY") && !x.getName.contains("_"))
        map += (x.getName -> x.getInt(null))
    })
    map
  }

  def question9(values: Array[Int], v: Int): (Int, Int, Int) = {
    (values.count {
      _ < v
    }, values.count {
      _ == v
    }, values.count {
      _ > v
    })
  }

  def printer(x: TraversableOnce[_]): Unit = println(x.mkString(x.getClass.getSimpleName + "(", ", ", ")"))

  // 有趣的写法，Scanner和StringTokenizer的高效结合
  def question2(path: String): scala.collection.mutable.Map[String, Int] = {
    val res = collection.mutable.Map[String, Int]()
    val in = new Scanner(path)
    while (in.hasNext()) {
      val st = new StringTokenizer(in.next())
      while (st.hasMoreTokens) {
        val key = st.nextToken()
        res(key) = res.getOrElse(key, 0) + 1
      }
    }
    res
  }

  def upperToLower: Map[Char, Char] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".zip("abcdefghijklmnopqrstuvwxyz").toMap
}
